package com.music.model;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

/**
 * Class allowing the recovery of characteristics of files mp3 
 * @author antho

	ID3v1: 128 bytes
	Field 		Length 	Description
	
	header 		3 		"TAG"
	title 		30 		30 characters of the title
	artist 		30 		30 characters of the artist name
	album 		30 		30 characters of the album name
	year 		4 		A four-digit year
	comment 	28||30	The comment.
	zero-byte 	1 		If a track number is stored, this byte contains a binary 0.
	track	 	1 		The number of the track on the album, or 0. Invalid, if previous byte is not a binary 0.
	genre 		1 		Index in a list of genres, or 255
	
	Extended tag (placed before the ID3v1 tag): 227 bytes
	Field 		Length 	Description
	
	header 		4 		"TAG+"
	title 		60 		Next 60 characters of the title (90 characters total)
	artist 		60 		Next 60 characters of the artist name
	album 		60 		Next 60 characters of the album name
	speed 		1 		0=unset, 1=slow, 2= medium, 3=fast, 4=hardcore
	genre 		30 		A free-text field for the genre
	start-time 	6 		the start of the music as mmm:ss
	end-time 	6 		the end of the music as mmm:ss
 */

public class Tags implements Data{

	private String track, artist, album, year, comment, genre, extension;
	private int num;
	private long size;

//	private String getID3Version(File file) throws IOException{ 
//		RandomAccessFile input = new RandomAccessFile(file, "r");
//		String result = null;
//		if(input.read() == 'I' && input.read() == 'D' && input.read() == '3'){
//			final int majorVersion = input.read();
//			for(int i=0; i<300; i++)
//				System.out.print((char)input.read());
//			switch (majorVersion){
//				case 0:
//					result = "ID3v2r0";
//					break;
//				case 3:
//					result = "ID3v2r3";
//					break;
//				case 4:
//					result = "ID3v2r4";
//					break;
//			}
//	    }
//		if (input.length() >= 128){
//			input.seek(input.length()-128);
//			if( input.readUnsignedByte() == 'T' && input.readUnsignedByte() == 'A' && input.readUnsignedByte() == 'G'){
//				// Check if there is a track number. If so, it's 1.1.
//				input.seek(input.length()-3);
//				final int trackNoMarker = input.readUnsignedByte();
//				final int rawTrackNo = input.readUnsignedByte();
//				if(trackNoMarker == 0){
//					if (rawTrackNo == 0){
//						// Could be either v1.0 or v1.1, so just report v1.
//						result = "ID3v1";
//					}
//					else{
//						// Definitely v1.1.
//						result = "ID3v1r1";
//					}
//				}
//			}
//		}
//		return result;
//	}
	
	/**
	 * reads an ID3tag from a file
	 * @param file
	 * @throws IOException 
	 * **/
	public void readTag (File file) throws IOException{
		if (file.exists()){
			//get the extension of the file
			String s = file.getAbsolutePath();
			int i = s.length()-1;
			while(s.charAt(i) != '.')
				i--;
			this.extension = s.substring(i+1);
			RandomAccessFile f = new RandomAccessFile (file, "r");
			//get the size of the file
			this.size = f.length();
			if (this.size < 128) {
				f.close();
				return;
			}
			f.seek(this.size - 128);
			byte[] tagID = new byte[3];
			byte[] track = new byte[30];
			byte[] artist = new byte[30];
			byte[] album = new byte[30];
			byte[] year = new byte[4];
			byte[] comment = new byte[28];
			byte[] genre = new byte[1];
			
			//check if the file contain a tag
			f.readFully(tagID);
			if (!(new String(tagID)).equals("TAG")) {
				f.close();
				return;
			}
			
			//read track
			f.readFully(track);
			this.track = new String(track).trim();
			
			//read artist
			f.readFully(artist);
			this.artist = new String(artist).trim();
			
			//read album
			f.readFully(album);
			this.album = new String(album).trim();
			
			//read year
			f.readFully(year);
			this.year = new String(year).trim();
			
			//read comment
			f.readFully(comment);
			this.comment = new String(comment).trim();
			
			//read number of the track
			if(f.read() == 0)
				this.num = f.read();
			else this.num = 0;
			
			//read genre of the track
			f.readFully(genre);
			this.genre = ((int)genre[0] < Data.TAB_GENRE.length && (int)genre[0] >= 0) ? Data.TAB_GENRE[(int)genre[0]] : Data.TAB_GENRE[Data.TAB_GENRE.length-1];
			
			f.close();
		}
	}
	
	/**
	 * write an ID3 tag to a file.
	 * @param file
	 * @throws IOException 
	 **/
	public boolean writeTag (File file) throws IOException{
		if (file.exists()){
			RandomAccessFile f = new RandomAccessFile (file, "rw");
			f.seek (f.length() - 128);
			
			//write tag balise
			f.writeBytes ("TAG");
			
			//write track name
			StringBuffer track = (this.track != null) ? new StringBuffer(this.track) : new StringBuffer();
			track.setLength(30);
			f.writeBytes(track.toString());
			
			//write artist
			StringBuffer artist = (this.artist != null) ? new StringBuffer(this.artist) : new StringBuffer();
			artist.setLength(30);
			f.writeBytes(artist.toString());
			
			//write album 
			StringBuffer album = (this.album != null) ? new StringBuffer(this.album) : new StringBuffer();
			album.setLength(30);
			f.writeBytes (album.toString());
			
			//write year
			StringBuffer year = (this.year != null) ? new StringBuffer(this.year) : new StringBuffer();
			year.setLength(4);
			f.writeBytes (year.toString());
			
			//write comment
			StringBuffer comment = (this.comment != null) ? new StringBuffer(this.comment) : new StringBuffer();
			comment.setLength(28);
			f.writeBytes(comment.toString());
			
			//write number
			f.writeByte(0);
			f.writeByte(this.num);
			
			//write comment
			int i = 0;
			boolean find = false;
			while(i<255 && !find)
				if(Data.TAB_GENRE[i].equals(this.genre))
					find = true;
				else i++;
			f.writeByte(i);
			
			f.close();
			return true;
		}
		return false;
	}

	////////////////////////////////////////////////////////////////////////////////////////
	////////							GETTER SETTER								////////						
	////////////////////////////////////////////////////////////////////////////////////////
	
	/*
	 * Getters
	 */
	
	/**
	 * @return the title of the track
	 */
	public String getTitle() {return this.track;}
	/**
	 * @return the name of the artist
	 */
	public String getArtist() {return this.artist;}
	/**
	 * @return the name of the album
	 */
	public String getAlbum() {return this.album;}
	/**
	 * @return the year of the album
	 */
	public String getYear() {return this.year;}
	/**
	 * @return the comment
	 */
	public String getComment() {return this.comment;}
	/**
	 * @return the genre of the track
	 */
	public String getGenre() {return this.genre;}
	/**
	 * @return the number of the track
	 */
	public int getTrack() {return this.num;}
	/**
	 * @return the size of the track
	 */
	public long getSize(){return this.size;}
	/**
	 * @return the extension of the file
	 */
	public String getExtension(){return this.extension;}
	
	/*
	 * Setters
	 */
	
	/**
	 * @param track
	 */
	public void setTitle(String track) {this.track = track;}
	/**
	 * @param artist
	 */
	public void setArtist(String artist) {this.artist = artist;}
	/**
	 * @param album
	 */
	public void setAlbum(String album) {this.album = album;}
	/**
	 * @param year
	 */
	public void setYear(String year) {this.year = year;}
	/**
	 * @param comment
	 */
	public void setComment(String comment) {this.comment = comment;}
	/**
	 * @param genre
	 */
	public void setGenre(String genre) {this.genre = genre;}
	/**
	 * @param num
	 */
	public void setTrack(int num) {this.num = num;}
}

